
package com.flashextended.apps.logomaker.view.core.workarea
{
	import com.flashextended.apps.logomaker.beans.workareaobjects.GenericObject;
	import com.flashextended.apps.logomaker.beans.workareaobjects.TextOnStage;
	import com.flashextended.apps.logomaker.controlers.Controlers;
	import com.flashextended.apps.logomaker.demologo.DemoLogo;
	import com.flashextended.apps.logomaker.singleton.AppControl;
	import com.flashextended.apps.logomaker.singleton.AppLocales;
	import com.flashextended.utils.movement.transformationtool.Handler;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	import mx.collections.ArrayCollection;
	import mx.containers.Canvas;
	import mx.controls.Alert;
	import mx.core.ScrollPolicy;
	import mx.effects.Move;
	import mx.events.ResizeEvent;

	public class Workarea extends Canvas
	{
		private var graphicObjects:ArrayCollection;
		private var handler:Handler;
		private var reference:GenericObject;
		
		public function Workarea()
		{
			super();
			settings();
			graphicObjects = new ArrayCollection();
			AppControl.getInstance().workarea = this;
			this.clipContent = true;
			this.verticalScrollPolicy = ScrollPolicy.OFF;
			this.horizontalScrollPolicy = ScrollPolicy.OFF;
			
			if(AppLocales.firstRun)
			{
				AppLocales.firstRun = false;
				//display demo logo
				this.addEventListener(ResizeEvent.RESIZE, containerReadyHandler);
			}
		}
		
		/**
		 * get graphic objects
		 * @see Model
		 */ 
		public function getGraphicObjects():ArrayCollection
		{
			return graphicObjects;
		}
		
		private function containerReadyHandler(e:Event):void
		{
			this.removeEventListener(ResizeEvent.RESIZE, containerReadyHandler);
			//display demo logo
			var demoLogo:DemoLogo = new DemoLogo();
		}
		
		public function help():void
		{
			for(var i:int=0;i<graphicObjects.length;i++)
			{
				var go:GenericObject = GenericObject(graphicObjects[i]);
				Alert.show("type="+go.type+" x: "+go.x.toString()+" y: "+go.y.toString()+
				" width="+go.width.toString()+" height="+go.height.toString());
			}
		}
		
		private function settings():void
		{
			this.percentWidth = 100;
			this.percentHeight = 100;
		}
		
		/**
		 * Add object to workarea
		 * @o - (ImageOnStage, TextOnStage or SymbolOnStage
		 */ 
		public function addObject(o:GenericObject):void
		{
			graphicObjects.addItem(o);
			this.addChild(o);
			o.move(this.width/2-o.width/2, this.height/2-o.height/2);
			removeHandler();
			addHandler(o);
			Controlers.getInstance().addMouseAction(o, Controlers.getInstance().selectObjectWorkarea);
			//PopUpManager.addPopUp(new GenericInfoWindow(500, 300, "Info"), this);
		}
		
		public function addExtractedObject(o:GenericObject):void
		{
			graphicObjects.addItem(o);
			this.addChild(o);
			removeHandler();
			addHandler(o);
			Controlers.getInstance().addMouseAction(o, Controlers.getInstance().selectObjectWorkarea);
			//PopUpManager.addPopUp(new GenericInfoWindow(500, 300, "Info"), this);
		}		
		
		/**
		 * remove transformation tool
		 */ 
		public function removeHandler():void
		{
			if(handler!=null)
			{
				try{
					
				this.removeChild(handler);
				handler = null;
				}catch(e:Error){}
			}
		}
		/**
		 * Add transformation tool
		 */ 
		public function addHandler(obj:GenericObject):void
		{
			this.reference = obj;
			removeHandler();
			handler = new Handler(reference, this.width, this.height, 0xFF6600);
			this.addChild(handler);
			handler.addEventListener("bringObject", bringObjectToPosition);
			handler.addEventListener("doubleClick", doubleClick);
			if(obj.type == TextOnStage.TYPE)
			{
				handler.toolTip = AppLocales.getInstance().data.locales["doubleClickText"];
			}
			else
			{
				handler.toolTip = "";
			}
			AppControl.getInstance().properties.openProperties(obj);
		}
		private function bringObjectToPosition(e:Event):void
		{
			//var t:TweenLite = new TweenLite(reference, .3, {x:handler.x, y:handler.y, onComplete: onFinishTween});
			var mv:Move = new Move(reference);
			mv.xFrom = reference.x;
			mv.yFrom = reference.y;
			mv.xTo = handler.x;
			mv.yTo = handler.y;
			mv.duration = 250;
			mv.end();
			mv.play();
		}
		
		private function doubleClick(e:Event):void
		{
			if(reference.type == TextOnStage.TYPE)
			{
				TextOnStage(reference).isFocus = true;
			}
		}
		
		/**
		 * Incomming selection task from Controlers.as
		 */ 
		public function selectObject(obj:GenericObject):void
		{
			addHandler(obj);
			for(var i:int=0;i<graphicObjects.length;i++)
			{
				if(GenericObject(graphicObjects.getItemAt(i)).type == TextOnStage.TYPE)
				{
					TextOnStage(graphicObjects.getItemAt(i)).isFocus = false;
				}
			}
		}
		
		/**
		 * Unselct all objects
		 */ 
		public function unselectObjects():void
		{
			removeHandler();
			for(var i:int=0;i<graphicObjects.length;i++)
			{
				if(GenericObject(graphicObjects.getItemAt(i)).type == TextOnStage.TYPE)
				{
					TextOnStage(graphicObjects.getItemAt(i)).isFocus = false;
				}
			}
			AppControl.getInstance().properties.closeProperties();		
		}
		
		
		/**
		 * Move OBJECT UP
		 */
		 public function moveObjectUp():void
		 {
		 	for(var i:int=0;i<graphicObjects.length;i++)
		 	{
		 		if(GenericObject(graphicObjects.getItemAt(i)) == this.reference)
		 		{
		 			if(i!=graphicObjects.length-1)
		 			{
		 				this.removeChildAt(i);
		 				this.addChildAt(this.reference, i+1);
		 				graphicObjects.removeItemAt(i);
		 				graphicObjects.addItemAt(this.reference, (i+1));
		 			}else
		 			{
		 				//Alert.show("First On Top");
		 				//restrict up movement for this object
		 			}
		 			checkUpDownAvailability();
		 			break;
		 		}
		 	}
		 }
		/**
		 * Move OBJECT UP
		 */
		 public function moveObjectDown():void
		 {
		 	for(var i:int=0;i<graphicObjects.length;i++)
		 	{
		 		if(GenericObject(graphicObjects.getItemAt(i)) == this.reference)
		 		{
		 			if(i!=0)
		 			{
		 				this.removeChildAt(i);
		 				this.addChildAt(this.reference, i-1);
		 				graphicObjects.removeItemAt(i);
		 				graphicObjects.addItemAt(this.reference, (i-1));
		 			}else
		 			{
		 				//Alert.show("First On Bottom");
		 				//restrict down movement for this object
		 			}
		 			checkUpDownAvailability();
		 			break;
		 		}
		 	}
		 }
		/**
		 * Remove Object
		 */
		 public function removeObject():void
		 {
		 	for(var i:int=0;i<graphicObjects.length;i++)
		 	{
		 		if(GenericObject(graphicObjects.getItemAt(i)) == this.reference)
		 		{
		 			this.removeChildAt(i);
		 			graphicObjects.removeItemAt(i);
		 			removeHandler();
		 			AppControl.getInstance().properties.closeProperties();
		 			break;
		 		}
		 	}
		 }		 
		 
		 public function checkUpDownAvailability():void
		 {
		 	//AppControl.getInstance().properties.downMovementAvailable(false);
			for(var i:int=0;i<graphicObjects.length;i++)
			{
				try{
					if(GenericObject(graphicObjects.getItemAt(i)) == this.reference)
					{
						if(i==graphicObjects.length-1)
						{
							AppControl.getInstance().properties.upMovementAvailable(false);
						}
						else
						{
							AppControl.getInstance().properties.upMovementAvailable(true);
						}
						if(i==0)
						{
							AppControl.getInstance().properties.downMovementAvailable(false);
						}
						else
						{
							AppControl.getInstance().properties.downMovementAvailable(true);
						}				
					}
				}catch(e:Error)
				{
					trace("Chech buttons availibility Error");
				}
			}		 	
		 }	 
		
		
		
		
		// BEGIN EXTERNAL API
		
		public function get getHandler():Handler
		{
			return handler;
		}
		/**
		 * Set Objects to workarea
		 * TBD - implemented for the save/load project version
		 */ 
		public function set objects(o:ArrayCollection):void
		{
			graphicObjects = o;
		}
		/**
		 * Get Objects to workarea
		 * TBD - implemented for the save/load project version
		 */		
		public function get objects():ArrayCollection
		{
			return graphicObjects;
		}
		
		public function getReferenceObject():GenericObject
		{
			return reference;
		}
		
		/**
		 * Returns the created logo
		 * calculates the minimum && maximum XY and draws a bitmapData with the objects on stage
		 */ 
		public function getLogo():Bitmap
		{
			removeHandler();
			var ordonatedArrayX:Array = extractRectangle()[0].sortOn("px", Array.NUMERIC);
			var ordonatedArrayY:Array = extractRectangle()[1].sortOn("py", Array.NUMERIC);
			var poz1:Point = new Point(ordonatedArrayX[0].px, ordonatedArrayY[0].py);
			var poz2:Point = new Point(ordonatedArrayX[ordonatedArrayX.length-1].px, ordonatedArrayY[ordonatedArrayY.length-1].py);
			
			var bmd:BitmapData = new BitmapData(this.width, this.height, true, 0xFFFFFF);
			bmd.draw(this, new Matrix(), null, null, null, true);			
			
			var bmd_width:Number = (poz2.x-poz1.x)+10;
			var bmd_height:Number = (poz2.y-poz1.y)+10;
			var actualBMD:BitmapData = new BitmapData(bmd_width, bmd_height, true, 0xFFFFFF);
			
			var sourceRect:Rectangle = new Rectangle(poz1.x, poz1.y, bmd_width, bmd_height);
        	var destPoint:Point = new Point(5,5);
        	actualBMD.copyPixels(bmd, sourceRect, destPoint);	
			addHandler(this.reference);
			return new Bitmap(actualBMD);
		}
		
		private function extractRectangle():Array
		{
			var main_arX:Array = new Array();
			var main_arY:Array = new Array();			
			for(var i:int=0;i<graphicObjects.length;i++)
			{
				var ob:GenericObject = GenericObject(graphicObjects[i]);
				var temp_arX:Array = new Array();
				temp_arX = convertPoints(ob)[0];
				var temp_arY:Array = new Array();
				temp_arY = convertPoints(ob)[1];
				
				for(var j:int=0;j<temp_arX.length;j++)
				{
					main_arX.push({px:Number(temp_arX[j]).toString()});
					main_arY.push({py:Number(temp_arY[j]).toString()});
				}
			}
			var all_XY:Array = new Array();
			all_XY.push(main_arX);
			all_XY.push(main_arY);
			return all_XY;
		}
		private function convertPoints(ob:GenericObject):Array
		{
			var ar:Array = new Array();
			var arX:Array = new Array();
			var arY:Array = new Array();
			
			var po1:Point = new Point(0, 0);
			var po2:Point = new Point(ob.width, 0);
			var po3:Point = new Point(ob.width, ob.height);
			var po4:Point = new Point(0, ob.height);
			po1 = ob.localToGlobal(po1);
			po2 = ob.localToGlobal(po2);
			po3 = ob.localToGlobal(po3);
			po4 = ob.localToGlobal(po4);
				
			var po11:Point = new Point(po1.x, po1.y);
			var po22:Point = new Point(po2.x, po2.y);
			var po33:Point = new Point(po3.x, po3.y);
			var po44:Point = new Point(po4.x, po4.y);
				
			po11 = ob.parent.globalToLocal(po11);
			po22 = ob.parent.globalToLocal(po22);
			po33 = ob.parent.globalToLocal(po33);
			po44 = ob.parent.globalToLocal(po44);
				
			arX.push(po11.x);
			arX.push(po22.x);
			arX.push(po33.x);
			arX.push(po44.x);
			
			arY.push(po11.y);
			arY.push(po22.y);
			arY.push(po33.y);
			arY.push(po44.y);
			
			ar.push(arX);
			ar.push(arY);			
			return ar;
		}			
		
	}
}